package com.zhdl.modules.eastdosing.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.common.util.DelayUtil;
import com.zhdl.common.util.WebResult;
import com.zhdl.hardware.io.smartLink.repository.impl.IOCmdHandleDaoImpl;
import com.zhdl.hardware.motor.buke.repository.impl.BukePortCmdHandle;
import com.zhdl.hardware.robot.borunte.repository.impl.BorunteCmdHandleDaoImpl;
import com.zhdl.hardware.robot.borunte.service.BorunteCmdSendService;
import com.zhdl.hardware_modules.service.DeviceService;
import com.zhdl.modules.autopick.entity.CameraCoordinate;
import com.zhdl.modules.autopick.entity.WestData;
import com.zhdl.modules.autopick.repository.CameraRepository;
import com.zhdl.modules.autopick.web.response.NewMemDevice;
import com.zhdl.modules.eastdosing.EastDosingProcess;
import com.zhdl.modules.eastdosing.NewCameraProcess;
import com.zhdl.modules.eastdosing.entity.EastDataResp;
import com.zhdl.modules.logging.service.OptRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.zhdl.modules.eastdosing.EastDosingProcess.isRunning;
import static com.zhdl.modules.eastdosing.EastDosingProcess.isTest;

@Slf4j
@RestController
@RequestMapping(path = "/eastDosing", produces = MediaType.APPLICATION_JSON_VALUE)
public class EastDosingController {
    @Resource
    private DeviceService deviceService;
    @Resource
    EastDosingProcess eastDosingProcess;
    @Resource
    BorunteCmdSendService borunteCmdSendService;
    @Resource
    BorunteCmdHandleDaoImpl borunteCmdHandleDao;
    @Resource
    private BukePortCmdHandle bukePortCmdHandle;
    @Resource
    private IOCmdHandleDaoImpl ioHandleDao;
    @Resource
    public CameraRepository cameraRepository;
    private static final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    private final Map<Integer, SseEmitter> sseEmitters = new ConcurrentHashMap<>();
    private long sseSeq;

    /**
     * 首页数据请求
     */
    @GetMapping(value = "/sse/{id}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter handleSse(@PathVariable Integer id) {
        log.info(id.toString());
        SseEmitter emitter = new SseEmitter();
        sseEmitters.put(id, emitter);
        // 超时移除
        emitter.onTimeout(() -> {
            emitter.complete();
            sseEmitters.remove(id);
        });
        // 完成移除
        emitter.onCompletion(() -> sseEmitters.remove(id));
        // 每一秒发送一条消息
        executorService.scheduleAtFixedRate(() -> {
            ObjectMapper mapper = new ObjectMapper();

//            NewMemDevice newNemDevice = new NewMemDevice();
//            List<NewMemDevice.CheckInfo> checkInfoList = new ArrayList<>();
//            checkInfoList.add(new NewMemDevice.CheckInfo("机器人连接检测", 1));
//            checkInfoList.add(new NewMemDevice.CheckInfo("3D相机连接检测", 1));
//            checkInfoList.add(new NewMemDevice.CheckInfo("远程IO连接检测", 1));
//            newNemDevice.setCheckInfos(checkInfoList);
//
//            newNemDevice.setNorthernCount(1 + "");
//            newNemDevice.setSouthCount(1 + "");
//            newNemDevice.setStatusDoor(1 == 1 ? "1" : "0");
//            newNemDevice.setRobotInit(true ? "1" : "0");
//            newNemDevice.setStatusStart(true ? "1" : "0");
//            newNemDevice.setStatusRunning(true ? "1" : "0");


            //加载内存数据
            WebResult<NewMemDevice> sseResp = WebResult.okResult(eastDosingProcess.newNemDevice);
//            WebResult<NewMemDevice> sseResp = WebResult.okResult(newNemDevice);
            try {
                emitter.send(SseEmitter.event().id(String.valueOf(getSseSeq())).data(mapper.writeValueAsString(sseResp), MediaType.APPLICATION_JSON));
                log.info("send" + sseResp);
            } catch (IOException e) {
                emitter.complete();
            }
        }, 0, 1, TimeUnit.SECONDS);

        return emitter;
    }

    /**
     * 获取SSE序号
     */
    private long getSseSeq() {
        if (sseSeq > 65535L * 65535)
            sseSeq = 0;
        return sseSeq++;
    }



    /**
     * 流程-清除数据库信息
     */
    @GetMapping("/clearCamera")
    public WebResult<String> clearCamera(int florNum) {

        florNum = 9 - florNum;
        /*
            清除数据库数据，从新识别
         */
        Optional<CameraCoordinate> byId = cameraRepository.findById(1);
        CameraCoordinate coordinate = byId.get();
        coordinate.setCameraParam("");
        coordinate.setFlorNum(florNum);
        coordinate.setBagNum(0);
        cameraRepository.save(coordinate);

        /*
            重启流程
         */
        EastDosingProcess.orationType = -1;
        EastDosingProcess.processRestart();

        return WebResult.okResult("clear mysql success!");
    }

    @Resource
    private OptRecordService optRecordService;

    /**
     * 流程 - 设置调试模式
     */
    @GetMapping("/processStart")
    public WebResult<String> processStart(boolean open) {
        /* 0为自动 1为手动 */
        if (open) {
            isTest = true;
            deviceService.setProcessMode(1);
            optRecordService.saveRecords("程序-设置模式为手动");
        } else {
            isTest = false;
            deviceService.setProcessMode(0);
            optRecordService.saveRecords("程序-设置模式为自动");
        }
        /* sse暂时停止，不处理情况 */
//        eastDosingProcess.sseResp.setProcessMode(isTest);
        return WebResult.okResult("Process set up: " + open + " success!");
    }

    @GetMapping("/motorRun4")
    public WebResult<String> motorRun4(int id) {
        int sensorId = idToSensorId(id);
        if (isTest) {
            optRecordService.saveRecords("程序-控制电机运动给料斗加药" + id);
            eastDosingProcess.eastDosingProcess(sensorId);
            return WebResult.okResult("move success!");
        } else {
            optRecordService.saveRecords("程序-控制电机运动给料斗加药" + "，但是失败,因为流程正在运行中");
            return WebResult.failResult("move fail!");
        }
    }

    public int idToSensorId(int id) {
        if (id == 1) {
            return 8;
        } else if (id == 2) {
            return 14;
        }
        return 999;
    }

    /**
     * 东区电机-初始化
     */
    @GetMapping("motorInit")
    public WebResult<String> motorEasternRun(int destinationValue, int tSpeedValue) {
        ioHandleDao.init("192.168.1.108:502");
//        ioHandleDao.init("127.0.0.1:502");
        bukePortCmdHandle.addPort("2");
        // ioWebsocketService.ioInit();
        log.info("ioHandleDao" + ",bukePortCmdHandle init");
        return WebResult.okResult("IO INIT!");
    }

    /**
     * 东区电机移动-电机运动
     */
    @GetMapping("/motorEasternRun")
    public WebResult<String> motorEasternRun(String slaveId, Integer destinationValue, Integer tSpeedValue) {
        //控制东区电机移动
        bukePortCmdHandle.bukeMotorRun("2", slaveId, destinationValue, tSpeedValue);
        return WebResult.okResult("Eastern motor already run : move distance is " + destinationValue + " pulse, speed is " + tSpeedValue + " , success!");
    }

    /**
     * 东区电机移动-电机停止
     */
    @GetMapping("/motorEasternStop")
    public WebResult<String> motorEasternStop(String slaveId) {
        //控制东区电机-停止运动
        bukePortCmdHandle.bukeMotorNoReady("2", slaveId);
        return WebResult.okResult("Eastern motor already stop success!");
    }

    @GetMapping("/eastData")
    public WebResult<String> eastData() {
        EastDataResp eastDataResp = eastDosingProcess.eastDataResp;
        String content = "";
        content += eastDataResp.getRobotDataOne() + ",";
        content += eastDataResp.getRobotDataTwo() + ",";
        content += eastDataResp.getRobotDataThree() + ",";
        content += eastDataResp.getRobotDataFour();
        return WebResult.okResult(content);
    }

    @GetMapping("/test")
    public WebResult<String> test() {
        borunteCmdHandleDao.init("127.0.0.1:502");
        DelayUtil.delayedExecution(1000, new Runnable() {
            @Override
            public void run() {
                borunteCmdSendService.borunteSetPickLocation(new int[]{0, 0, 0});
            }
        });
        return WebResult.okResult("Eastern motor already stop success!");
    }
    @Resource
    NewCameraProcess newCameraProcess;
    @GetMapping("/startCamera")
    public WebResult<String> startCamera() {
        optRecordService.saveRecords("相机-相机拍照");
        newCameraProcess.startCamera();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/cameraToRobot")
    public WebResult<String> cameraToRobot() {
        eastDosingProcess.startCamera();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/startProcess")
    public WebResult<String> startProcess() {
        optRecordService.saveRecords("程序-启动程序");
        EastDosingProcess.isStart = true;
        eastDosingProcess.reStart();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/stopProcess")
    public WebResult<String> stopProcess() {
        optRecordService.saveRecords("程序-停止程序");
        EastDosingProcess.isStart = false;
        isRunning = false;
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/initRobot")
    public WebResult<String> initRobot() {
        optRecordService.saveRecords("机器人-初始化按钮");
        eastDosingProcess.initRobot();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/testRun")
    public WebResult<String> testRun() {
        eastDosingProcess.testRun(new Random().nextInt(2));
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/openDoor")
    public WebResult<String> openDoor() {
        eastDosingProcess.openDoor();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/closeDoor")
    public WebResult<String> closeDoor() {
        eastDosingProcess.closeDoor();
        return WebResult.okResult("Eastern startCamera success!");
    }
    @GetMapping("/openScreen")
    public WebResult<String> openScreen(String pwd) {
        if (pwd.equals("123456")){
            optRecordService.saveRecords("用户登陆");
            return WebResult.okResult("ok");
        }else{
            return WebResult.okResult("fail");
        }
    }

    @GetMapping("/cassetteCountZero")
    public WebResult<String> cassetteCountZero() {
        optRecordService.saveRecords("加药记录清零");
        eastDosingProcess.cassetteCountZero();
        return WebResult.okResult("ok");
    }
}
